/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import fs from '@ohos.file.fs';
import util from '@ohos.util';

export class FileReader {
  // size of the file
  fileLength: number = 0
  // data length
  length: number = 0
  // read & write stream
  stream: fs.Stream | null = null
  // cache buf
  data: Uint8Array;

  constructor(path: string) {
    if (!path) {
      throw new Error("FileReader path is null");
    }
    this.stream = fs.createStreamSync(path, 'r+');
    let stat: fs.Stat = fs.statSync(path);
    this.fileLength = stat.size;
    let buf: ArrayBuffer = new ArrayBuffer(this.fileLength);
    let option = new Option();
    option.offset = 0;
    option.length = this.fileLength;
    this.stream.readSync(buf, option);
    this.data = new Uint8Array(buf);
  }

  /**
   * read file data
   */
  readLine(): string {
    let startPosition: number = this.length
    let textDecoder = util.TextDecoder.create('utf-8', { ignoreBOM: true })
    while (this.length <= this.fileLength) {
      let bufArray: number[] = Array.from(this.data.subarray(this.length, this.length + 1))
      this.length++
      let temp = String.fromCharCode(...bufArray)
      if (temp == '\r') {
        let array: number[] = Array.from(this.data.subarray(this.length - 1, this.length + 1))
        if (String.fromCharCode(...array) == "\r\n") {
          this.length++
        }
        return textDecoder.decodeWithStream(this.data.subarray(startPosition, this.length), { stream: false })
      } else if (temp == '\n') {
        return textDecoder.decodeWithStream(this.data.subarray(startPosition, this.length), { stream: false })
      }
    }
    this.length--
    return textDecoder.decodeWithStream(this.data.subarray(startPosition, this.length), { stream: false })
  }

  /**
   * check file is end or not
   */
  isEnd() {
    return this.fileLength <= 0 || this.length == this.fileLength
  }

  /**
   * close stream
   */
  close() {
    if (!!this.stream) {
      this.stream.closeSync()
    }
  }
}

class Option {
  offset: number = 0;
  length: number = 0;
}